package fun.rockchen.aop;

import fun.rockchen.anno.SystemControllerLog;
import fun.rockchen.bean.AdminLog;
import fun.rockchen.utils.LogUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author Rock Chen
 * @Description:
 * @date 2023/10/1 15:49
 */
@Aspect
@Component
public class SystemLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);

    /**
     * 定义切点
     * Controller层切点 注解拦截
     */
    @Pointcut("@annotation(fun.rockchen.anno.SystemControllerLog) || @within(fun.rockchen.anno.SystemControllerLog)")
    public void logPointCut() {
    }

    /**
     * 切面
     */
    @Around(value = "logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) {

        logger.info("调用日志监控");
        AdminLog adminLog = new AdminLog();
        /*从切面值入点获取植入点方法*/
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        /*获取切入点方法*/
        Method method = signature.getMethod();
        /*获取方法上的值*/
        SystemControllerLog systemControllerLog = method.getAnnotation(SystemControllerLog.class);
        /*保存操作事件*/
        if (systemControllerLog != null) {
            String operation = systemControllerLog.operation();

            adminLog.setOperation(operation);
            /*保存日志类型*/
            adminLog.setOperation(operation);
            String type = systemControllerLog.type();
            adminLog.setType(type);
            /*打印*/
            logger.info("操作事件 :" + operation);
            logger.info("事件类型为:" + type);
        }
        /*获取请求体内容*/
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String requestUri = request.getRequestURI();/*获取请求地址*/
        String requestMethod = request.getMethod();/*获取请求方式*/
        String remoteAddr = LogUtil.getIpAddress(request);
        /*存请求地址，请求方式，请求IP*/
        adminLog.setRemoteAddr(remoteAddr);
        logger.info("客户端IP为：" + remoteAddr);
        adminLog.setRequestUri(requestUri);
        logger.info("请求路径为：" + requestUri);
        adminLog.setMethod(requestMethod);
        logger.info("请求方式为：" + requestMethod);
        /*获取参数*/
        Object[] args = joinPoint.getArgs();
        if (args != null) {
            for (Object obj : args) {
                /*   System.out.println("传递的参数" + obj);*/
                String params = obj.toString();
                /*      System.out.println("传递的参数" + params);*/
                logger.info("请求参数为：" + params);
                /*保存请求参数*/
                adminLog.setParams(params);
            }
        }
        Object proceed = null;

        try {
            //执行增强后的方法
            proceed = joinPoint.proceed();
            if (method.isAnnotationPresent(SystemControllerLog.class)) {
                adminLog.setExceptionLog("无异常");
                adminLog.setType("info");
                adminLog.setResultParams(proceed.toString());

            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            adminLog.setExceptionLog(throwable.getMessage());
            adminLog.setType("Err");
            assert proceed != null;
            adminLog.setResultParams(proceed.toString());

        }
        logger.info("返回参数为" + proceed);
        return proceed;
    }
}


